/*	
	Universidad: Universidad Nacional de Río Cuarto (UNRC)
	Materia: Taller de Diseño de Software (Cod. 3306)
	Carrera: Licenciatura en Ciencias de la Computación
	Proyecto 2011: Compilador de un subconjunto del lenguaje C (C--).
	Integrantes:
		Bettiol, Matías Nicolas.
		Mattana, Diego Leonel.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../includes/Lista.h"

// Retorna una nueva lista.
Lista openLista(){
	return NULL;
}

// Retorna 0 si e1 == e2 sino retorna 1.
int equal(const TElemLista e1, const TElemLista e2){
	if((e1.tipo == e2.tipo) &&  (e1.nombre == e2.nombre)  )
		return 0;
	else
		return 1;
}

// Inserta un nuevo elemento en la lista.
// Retorna 0 si no se puede insertar.
int add(Lista *l , const TElemLista e){
	Lista nuevo;
	nuevo = malloc(sizeof (struct TElemLista));
	if(nuevo == NULL)
		return 1;
	nuevo->sig = (*l);
	nuevo->e = e;
	(*l) = nuevo;
	return 0;
}

// Borra el elemento "e" de la lista.
// Retorna 0 si el elemento es eliminado.
int del(Lista *l , const TElemLista e){
	Lista ant, del;
	int esta;
	esta = find((*l),e, &ant);
	if(esta == 1)
		return 1;
	if(esta == 0){
		if (*l != NULL) {
			NodoLista *ant = *l;
        	*l = (*l)->sig;
        	free(ant);
    	}
    	return 0;
  	}
	del = ant->sig;
	ant->sig = del->sig;
	free(del);
	return 0;
}

// Quita el primer elemento de la lista.
int desapila(Lista *l){
	if ((*l)!= NULL){
	    (*l) = (*l) -> sig;
	}
}

// @param *ant retorna un puntero previo del elemento.
// Retorna 0 si es el primer elemento.
// Retorna 1 si no encuentra el elemento "e".
// Retorna 2 si el elemento "e" es encontrado en otra posicion distinta.
// Aviso: *ant siempre es modificado.
int find(Lista l , const TElemLista e, Lista *ant){
	Lista act;
	(*ant) = NULL;
	act = l;
	if(l == NULL)
		return 1;
	while(act->sig != NULL && (strcmp(act->e.nombre,e.nombre))){
		(*ant) = act;
    	act = act->sig;
	}
	if((*ant) == NULL &&  (strcmp(act->e.nombre,e.nombre)) == 0){
    	return 0;
	}
	if((*ant) != NULL && (*ant)->sig != NULL && (strcmp((*ant)->sig->e.nombre,e.nombre)) == 0){
    	return 2;
  	}
  	return 1;
}

// @param *ant retorna un puntero previo del elemento.
// Retorna un puntero al elemento "e".
TElemLista* findElemento(Lista l , const TElemLista e, Lista *ant){
	Lista act;
	(*ant) = NULL;
	act = l;
	if(l == NULL)
		return ;
	while(act->sig != NULL && (strcmp(act->e.nombre,e.nombre))){
		(*ant) = act;
    	act = act->sig;
	}
	if((*ant) == NULL &&  (strcmp(act->e.nombre,e.nombre)) == 0){
		TElemLista *aux = &act->e;
    	return aux;
	}
	if((*ant) != NULL && (*ant)->sig != NULL && (strcmp((*ant)->sig->e.nombre,e.nombre)) == 0){
		TElemLista *aux = &(*ant)->sig->e;
    	return aux;
  	}
  	return ;
}

// Retorna 0 si la lista esta vacia.
// Retorna 1 si la lista no esta vacia.
int vaciaLista(Lista l){
	if(l == NULL)
		return 0;
	return 1;
}

// Retorna el tipo de "nombre".
char* retornaTipo(Lista l, const char* nombre, Lista *ant){
	Lista act;
	(*ant) = NULL;
	act = l;

	if(l == NULL){
		return "NULL";
	}
	while(act->sig != NULL && (strcmp(act->e.nombre,nombre))){
		(*ant) = act;
		act = act->sig;
	}
	if((*ant) == NULL && (strcmp(act->e.nombre,nombre)) == 0){
		return act->e.tipo;
	}
	if((*ant) != NULL && (*ant)->sig != NULL && (strcmp ((*ant)->sig->e.nombre,nombre)) == 0){
		return (*ant)->sig->e.tipo;
	}
	return "NULL";
}

// Retorna el subtope de la lista.
TElemLista* subTope(Lista *l){
 TElemLista *sub ; 
 sub = &(*l)->sig->e;
 return sub ;
}

// Retorna el tope de la lista.
TElemLista* tope(Lista *l){
 TElemLista *sub ; 
 sub = &(*l)->e;
 return sub ;
}

// Retorna el primer elemento de la lista.
TElemLista* popLista(Lista *l){
	TElemLista* e;
	e = &(*l)->e;
	(*l) = (*l)->sig; 
	return e;
}

// Imprime el elemento "e" de la lista.
void printTElemLista(const TElemLista e){ 
	int a = *e.nombre;
	if(e.label > 0){
		printf(" (%s , %i)",e.nombre,e.label);
	}
	else{
		if(strcmp(e.tipo,"int") == 0)
			printf(" (%s , %s , %d ,%i, %i, %i)",e.tipo,e.nombre,(unsigned int)e.nombre,e.valorI,e.offset,e.constante);
		else
			printf(" (%s , %s , %d ,%.3f, %i, %i)",e.tipo,e.nombre,(unsigned int)e.nombre,e.valorF,e.offset,e.constante);
	}
}

// Imprime la lista.
void printLista(Lista l){
	Lista act;
	act = l;
	if(l != NULL){
		printTElemLista(act->e);
		while(act->sig != NULL){
			act = act->sig;
			printTElemLista(act->e);
   		}
	}
	printf("\n");
}
